package com.snopy.leetcode.index1001_2000.index1601_1700;

import java.util.*;

/**
 * @author snopy
 * @version 1.0.0
 * @classname Question1606
 * @description defficult
 * 1606.找到处理最多请求的服务器
 * 你有k台服务器，编号为0~k-1,它们可以同时处理多个请求组。每个服务器有无穷的计算能力但是 无能同时处理超过一个请求。
 * 请求分配到服务器的规则如下：
 * ● 第i（序号从0开始）个请求到达
 * ● 如果所有服务器都已被占据，那么该请求被舍弃（完全不处理）
 * ● 如果第（i%k)个服务器空闲，那么对应服务会处理该请求
 * ● 否则，将请求安排给下一个空闲的服务器（服务器构成一个环，必要的话可能从第0个服务器开始继续找下一个空闲的服务器）。
 *   比方说，如果第i个服务器正忙，那么会查看第（i+1）个服务器，第（i+2）个服务器等等。
 *
 * 给你一个 严格递增的正整数数组arrival，表示第i个任务的到达时间，和另一个数组load，
 * 其中load[i]表示第i个请求的工作量（也就是服务器完成它所需要的时间）。
 * 你的任务是找到 最繁忙的服务器。最繁忙定义为一个服务器处理的请求数是所有服务器里最多的。
 *
 * 请你返回包含所有最繁忙服务器序号的列表，你可以以任意顺序返回这个列表。
 *
 * 
 *
 * 示例 1：
 *
 *
 *

 * @email 77912204@qq.com
 * @date 2022/03/30 19:37
 */
public class Question1606 {
    public static void main(String[] args) {
        TreeSet<Integer> available = new TreeSet<Integer>();
        available.add(0);
        available.add(1);
        Integer ceiling = available.ceiling(2);
        System.out.println(ceiling);
        Integer first = available.first();
        System.out.println(first);
    }

    public List<Integer> busiestServers(int k, int[] arrival, int[] load) {
        /*
        * 将空闲服务器放入有序集合
        * */
        TreeSet<Integer> available = new TreeSet<Integer>();
        for (int i = 0; i < k; i++) {
            available.add(i);
        }
        /*
        * 优先队列存放执行的任务，确保队首是执行时间最短的任务
        * */
        PriorityQueue<int[]> busy = new PriorityQueue<int[]>((a,b)-> a[0]-b[0]);
        int[] requests = new int[k];
        for (int i = 0; i < arrival.length; i++) {
            /*
            * 如果已处理请求的时间小于后续请求到来的时间，说明服务器处于空闲状态，可以处理新请求，否则舍弃该请求，有请下一个
            * */
            while (!busy.isEmpty() && busy.peek()[0] <= arrival[i]){
                available.add(busy.poll()[1]);
            }
            /*
            * 服务器都在忙碌，则舍弃当前请求
            * */
            if (available.isEmpty()){
                continue;
            }
            Integer p = available.ceiling(i % k);
            if (p == null){
                p = available.first();
            }
            /*
            * 服务器处理请求次数加1
            * */
            requests[p]++;
            /*
            * 向优先队列增加新的任务和对应处理请求的服务器编号
            * */
            busy.offer(new int[]{arrival[i] + load[i],p});
            /*
            * 对应编号服务正在处理请求，移除可以集合
            * */
            available.remove(p);
        }
        int maxRequest = Arrays.stream(requests).max().getAsInt();
        List<Integer> ret = new ArrayList<>();
        for (int i = 0; i < k; i++){
            if (requests[i] == maxRequest){
                ret.add(i);
            }
        }


        return ret;
    }
}
